home *** CD-ROM | disk | FTP | other *** search
- Date: Tue, 9 Feb 1999 20:53:34 -0500
- From: miff <miff@BLUE.9MM.COM>
- To: BUGTRAQ@netspace.org
- Subject: sl0scan (ambiguous source portscanner)
-
- hello all,
-
- I hear that maybe nmap does something similar to this, but I'm posting it anyway to see if there is
- enough interest for me to continue developing it. This is based on some code that I have been evolving
- for a while now.
-
- sl0scan features:
- - you select which ports to scan using comma separated lists and ranges at runtime
- - *identical* scans sent from as many hosts as you like
- - random generation of dummy hosts, or it can read a file of desired fake scanning sources (or both).
- - choose at what sequence to insert the real scan (say, #500 out of 1000 scans)
- - status shown on screen
-
- also:
- - written in easily modifiable perl; all packet components are in variables
-
- sl0scan drawbacks:
- - you have to sniff the response. This really isnt so bad; you just do "tcpdump src <scantarget>" in a
- seperate window and look for the big "R" or "S" from each port. (S means the port was open). If there
- is interest, I'll fold in the packet capture function in the next release.
- - it can be slow depending on how you use it
- - tcp only at this release
-
-
- #!/usr/bin/perl
- #
- # sl0scan v0.1
- # perl spoofer/scanner
- # based on lego
- #
- # written by miff Jan 1999
- #
- # i wrote this in response to all the
- # email i got from lego saying:
- # "i'm not getting a response from the
- # portscan!!&^@#$"
- #
- # this version requests the following:
- # - which ports to scan
- # - how many fake hosts to use
- # - the "real" ip (any sniffable ip)
- # - an optional file of "real" fakes
- # - when to insert the real scan
- #
- # you are responsible for sniffing the response,
- # at this point. maybe that'll be automatic
- # in the future.
- #
- # shouts: b_, X, kubiak, shinex, xyg, ReDragon, #9mm
- # also: Clovis (where ya at h0mez?)
- #
- # best musical artist: mike patton.
- #
-
- use Socket;
- use strict qw(refs, subs);
-
- my $delay = 1; # delay in seconds between scans. its really important
- # not to end up with a synflood here, that will break the
- # scan. use a large real fake file to avoid DoS.
-
- my $input, $dummy;
- print "Welcome to sl0scan, the slowest scanner on the net.\n";
- print "This program sends out a deluge of fake scans, and inserts \n";
- print " a real scan somewhere in between. In this version, you \n";
- print " must fire up a sniffer and watch for the responses to \n";
- print " the real scan... Hope you know what to look for \n";
- print "\n";
- print "ready?\n";
- $dummy = <>;
- print "good. here's where we axe you the 5 imp0tent questi0nz:\n\n";
- print "1.) what is the IP ADDY or HOSTNAME of the target? \n";
- $input = <>;
- chop $input;
- $target_box = $input;
- print "got $input.\n\n\n";
- print "2.) what be the true source of the scan? (any sniffable ip will do) \n";
- $input = <>;
- chop $input;
- $true_source = $input;
- print "got $input.\n\n\n";
- print "3.) how many fakes should we dump on this homies fro? \n";
- print "note: number of fakes will directly affect the sl0ness of the scan\n";
- print " to the tune of at least 1 second per host. we don wanna dos here.. \n";
- print " otoh, lots of fakes increase your invisibility \n";
- $input = <>;
- chop $input;
- $num_fakes = $input;
- print "got $input. <-- hope that was a number...\n\n\n";
- print "4.) which ports should we check? (IMPORTANT) \n";
- print " i recommend as few as possible, as this will *really* slow shit down\n";
- print "enter ports in the following format: COMMA DELIMITED, indicate ranges with dash\n";
- print " example: i want to scan ports 22 23 25 80 and 130-140. i say: \n";
- print "22,23,25,80,130-140\n";
- print "avoid spaces and extra shit. save that for another time. \n";
- $input = <>;
- chop $input;
- $portlist = $input;
- print "got $input. <-- if you screwed that up, bad shit is gonna happen.\n\n\n";
- print "5.) At what sequence would you like the real scan inserted? \n";
- print "note: this number must be <= the total number of fakes...\n";
- $input = <>;
- chop $input;
- $real_seq = $input;
- $real_seq--; #gotta decrement; we start wit 0
- print "got $input. <-- hope that was a number...\n\n\n";
- print "6.) ok last one. Would you like to use a file of desired fakes?\n";
- print "this gives you the advantage of choosing the fake ips, and \n";
- print "avoiding the situation that all of the fake scans came from \n";
- print "non-existent ips. i'd recommend using a large file here \n\n";
- print "also, if you use all fake ips, even with the one second delay, \n";
- print "you stand a greater chance of DOS'ing the target. which is bad.\n\n";
- print "fyi, the format for the file is 1 ip or hostname per line, no extra shit. \n\n";
- print " IF YOU WANT TO USE SUCH A FILE, enter the filename here:\n";
- $input = <>;
- chop $input;
- $frofile = $input;
- print "got $input. <-- hope that was a real file...\n\n\n";
- print "OK FOO, WE READY. YOU READY?\n";
- $dummy = <>;
-
- my @frobobs;
- my $frocount = -1;
- # ok, first order of bidniss: lets get that file open if it exists:
- if ($frofile ne '') {
- if (-e $frofile) {
- #we got a file...
- open (FROFILE, $frofile) || die "cant open file, kid";
- while ($input = <FROFILE>) {
- chop $input;
- $frocount++;
- @frobobs[$frocount] = $input;
- }
- close (FROFILE);
- # while we're at it, lets cal the percent of total fakes:
- $fro_percent = $frocount * 100 / $num_fakes;
- }
- }
-
- my $scancount = 0;
- my $src_box, $src_port;
- srand(time ^ $$);
-
- while ($scancount < $num_fakes) {
- # main driver routine
- if ($scancount == $real_seq) {
- #this is the real deal
- print "real scan!! (from $true_source) \n\n";
- $src_box = $true_source;
- } else {
- # grab a random number between 0 and $num_fakes
- if ($randum > $frocount) {
- #create one
- my $rand1 = int(rand(230)) + 20;
- my $rand2 = int(rand(255));
- my $rand3 = int(rand(255));
- my $rand4 = int(rand(255));
- $src_box = $rand1 . "." . $rand2 . "." . $rand3 . "." . $rand4;
- #for debugging:
- print "scan from $src_box \n";
- } else {
- # use the array
- $randum = int(rand($num_fakes));
- $src_box = @frobobs[$randum];
- print "we gon fro from $src_box \n";
- }
- }
- # now send the scan
- sc4n($target_box,$portlist,$src_box,$fake_port);
-
- # now sleep to avoid DoS:
- sleep($delay);
-
- $scancount++;
- }
-
-
- sub sc4n {
- my ($dest_host,$dest_ports,$src_host,$src_port) = @_;
-
- #print "in scan, got $dest_host,$dest_ports,$src_host,$src_port\n\n";
-
- #set constants:
- my ($PROTO_RAW) = 255; # from /etc/protocols
- my ($PROTO_IP) = 0; #ditto
- my ($IP_HDRINCL) = 1; #we set the ip header, thanks
-
- #look up mah shit...
- $dest_host = (gethostbyname($dest_host))[4];
- $src_host = (gethostbyname($src_host))[4];
-
- #time to open a raw socket....
- socket(S, AF_INET, SOCK_RAW, $PROTO_RAW) || die $!;
-
- #raw socket should be open...
- #now set the bad boy up...
- setsockopt(S, $PROTO_IP, $IP_HDRINCL, 1);
-
- # here we need to interpret the port list:
- my @ports1 = split (",",$dest_ports);
-
- my $psplit,$rcount,$range_low,$range_hi;
- my $p2count = 0;
- my @ports2;
- my @range;
-
- foreach $psplit (@ports1) {
- if ($psplit =~ '-') {
- # we have a range
- @range = split("-",$psplit);
- $range_low = @range[0];
- $range_hi = @range[1];
- $rcount = $range_low;
- while ($rcount <= $range_hi) {
- @ports2[$p2count] = $rcount;
- $p2count++;
- $rcount++;
- }
- } else {
- @ports2[$p2count] = $psplit;
- $p2count++;
- }
- }
-
- my $port;
-
- foreach $port (@ports2) {
- #build a tcp header:
-
- #vary the ports in here...
- $src_port = int(rand(60000));
-
- my ($packet) = givehead($src_host, $src_port, $dest_host, $port, $data);
- #bust out the destination...
- my ($dest) = pack('S n a4 x8', AF_INET, $port, $dest_host);
- #send a fux0ring packet
- send (S,$packet,0, $dest);
- }
-
- }
-
- sub givehead {
- my ($src_host, $src_port, $dest_host, $dest_port, $data) = @_;
-
- #HERE WE PLAY WITH THE INSIDES OF THE TCP PIECE
- #AND CALC THE TCP HDR CHECKSUM.
- my $hdr_cksum = 0; # we set it to 0 so we can calculate it
- my $zero = 0; #might need a zero from time to time
- my $proto_tcp = 6; # the protocol number for tcp
- my ($tcplength) = 20; # 20 byte tcp hdr; no data
- # IF YOU ADD DATA, MAKE SURE TO ADD ITS PACKED LENGTH
- # TO THE TCPLENGTH HERE!!!
- # all of the source and destination infoz is passed to us
- # screw wit it in the parent routine...
- my $syn = 790047533; # random syn; try to keep it under 32 bits :)
- my $ack = 0; # zero ack; try to keep it under 32 bits :)
- my $tcp_4bit_hdrlen = "5"; # 5 * 32bit (4 byte) = 20 bytes
- my $tcp_4bit_reserved = 0; # reserved for 0
- my $hdr_n_reserved = $tcp_4bit_hdrlen . $tcp_4bit_reserved; # pack them together
- my $tcp_urg_bit = 0; # URGENT POINTER BIT
- my $tcp_ack_bit = 0; # ACKNOWLEDGEMENT FIELD BIT
- my $tcp_psh_bit = 0; # PUSH REQUEST BIT
- my $tcp_rst_bit = 0; # RST (RESET CONNXION) BIT
- my $tcp_syn_bit = 1; # SYN FLAG BIT #its a syn!!
- my $tcp_fin_bit = 0; # FIN FLAG BIT
- # here we put together 2 reserved fields and the 6 flags to pack as binary.
- my $tcp_codebits = $zero . $zero . $tcp_urg_bit . $tcp_ack_bit . $tcp_psh_bit .
- $tcp_rst_bit . $tcp_syn_bit . $tcp_fin_bit;
- my $tcp_windowsize = 124; # default window size
- my $tcp_urgent_pointer = 0; # urgent pointer
-
-
- # the following is not a tcp header per se, but a pseudo header
- # used to calculate the tcp checksum. yes, its a pain in the ass.
- my ($pseudo_tcp) = pack ('a4 a4 C C
- n n n
- N N
- H2 B8
- n v n',
- $src_host,$dest_host,$zero,$proto_tcp,
- $tcplength,$src_port,$dest_port,
- $syn,$ack,
- $hdr_n_reserved,$tcp_codebits,
- $tcp_windowsize,$zero,$tcp_urgent_pointer);
-
- my ($tcp_chksum) = &checkfro($pseudo_tcp);
-
-
- # PLAY WITH THE INNARDS OF THE IP PIECE HERE!!!
- my $ip_version = "4"; # (nybble) tcp/ip version number (current is 4)
- my $ip_hedlen = "5"; # (nybble) number of 32-bit words in ip header
- my $ver_n_hlen = $ip_version . $ip_hedlen; # we pack 2 nybbles together
- my $ip_tos = "00"; # (byte) ip type-of-service
- my ($totlength) = $tcplength + 20; #tcp + 20 byte ip hdr ##
- ## we'll pack totlength into 2 bytes in the packet
- my $ip_fragment_id = 31337; # 2 bytes as well.
- my $ip_3bit_flags = "010"; # ip fragmentation flags (3 bits) (frag, do not frag)
- my $ip_13bit_fragoffset = "0000000000000"; #fragment offset
- my $ip_flags_n_frags = $ip_3bit_flags . $ip_13bit_fragoffset;
- my $ip_ttl = 64; # 64 seconds / hops
- # we have proto_tcp from above... my $proto_tcp = 6;
- # we have hdr_checksum from above...
- # all source and destination infoz is passed to us (it
- # gets set in parent routine)
- # change $syn and $ack above in tcp section
- # in fact, everything else in the packet is set above.
-
-
- my ($hdr) = pack ('H2 H2 n n
- B16 C2
- n a4 a4
- n n
- N N
- H2 B8
- n v n',
- $ver_n_hlen, $ip_tos, $totlength, $ip_fragment_id,
- $ip_flags_n_frags,$ip_ttl, $proto_tcp,
- $hdr_cksum, $src_host, $dest_host,
- # end of ip header, begin tcp header
- $src_port, $dest_port,
- $syn,$ack,
- $hdr_n_reserved,$tcp_codebits,
- $tcp_windowsize,$tcp_chksum,$tcp_urgent_pointer);
-
- return $hdr;
- }
-
- sub checkfro {
- #dis sekzhun robbed from someplace else....
- my (
- $msg # The message to checkfro
- ) = @_;
- my ($len_msg, # Length of the message
- $num_short, # The number of short words in the message
- $short, # One short word
- $chk # The checkfro
- );
-
- $len_msg = length($msg);
- $num_short = $len_msg / 2;
- $chk = 0;
- foreach $short (unpack("S$num_short", $msg))
- {
- $chk += $short;
- } # Add some lead
- $chk += unpack("C", substr($msg, $len_msg - 1, 1)) if $len_msg % 2;
- $chk = ($chk >> 16) + ($chk & 0xffff); # bust out mah fro pic
- return(~(($chk >> 16) + $chk) & 0xffff); # spray some jheri
- }
-
-
-